package com.cooper.android.comm;

import java.io.File;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import com.cooper.scraper.DownloadParams;
import com.cooper.scraper.HttpDownload;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.DownloadManager;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class DownAppInfoGetTask extends
		AsyncTask<String, Integer, DownAppInfoGetTask.AppVersionInfo> {

	private static final String DOWNLOADS_TAG = "downloads";
	private static final String DOWNLOAD_TAG = "download";

	public static class AppVersionInfo implements Parcelable {
		private List<String> verExceptions;
		private String description;
		private int releaseVer;
		private String url;
		private String name;
		private String title;
		private boolean downloading = false;
		private String completeFilePath;

		public Uri getCompleteFileUri() {
			if (completeFilePath == null) {
				return null;
			}
			return Uri.fromFile(new File(completeFilePath));
		}

		public boolean isDownComplete() {
			return completeFilePath != null;
		}

		public List<String> getVerExceptions() {
			return verExceptions;
		}

		public void setVerExceptions(List<String> verExceptions) {
			this.verExceptions = verExceptions;
		}

		public String getDescription() {
			if (description == null) {
				return "";
			} else
				return description;
		}

		public void setDescription(String description) {
			this.description = description;
		}

		public int getReleaseVer() {
			return releaseVer;
		}

		public void setReleaseVer(int newVer) {
			this.releaseVer = newVer;
		}

		public String getUrl() {
			return url;
		}

		public void setUrl(String url) {
			this.url = url;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getTitle() {
			return title;
		}

		public void setTitle(String title) {
			this.title = title;
		}

		public String getCompleteFilePath() {
			return completeFilePath;
		}

		public void setCompleteFilePath(String completeFilePath) {
			this.completeFilePath = completeFilePath;
		}

		public boolean isDownloading() {
			return downloading;
		}

		public void setDownloading(boolean downloading) {
			this.downloading = downloading;
		}

		public AppVersionInfo(List<String> verExceptions, String description,
				int releaseVer, String url, String name, String title,
				boolean downloading, String completeFilePath) {
			super();
			this.verExceptions = verExceptions;
			this.description = description;
			this.releaseVer = releaseVer;
			this.url = url;
			this.downloading = downloading;
			this.completeFilePath = completeFilePath;
		}

		public AppVersionInfo(int releaseVer, String url, String name,
				String title) {
			super();
			this.releaseVer = releaseVer;
			this.url = url;
			this.name = name;
			this.verExceptions = new ArrayList<String>();
			this.title = title;
		}

		@Override
		public int describeContents() {
			return 0;
		}

		@Override
		public void writeToParcel(Parcel dest, int flags) {
			dest.writeStringList(verExceptions);
			dest.writeString(description);
			dest.writeInt(releaseVer);
			dest.writeString(url);
			dest.writeString(name);
			dest.writeString(title);
			dest.writeByte((byte) (downloading ? 1 : 0));
			dest.writeString(completeFilePath);
		}

		public static final Parcelable.Creator<AppVersionInfo> CREATOR = new Creator<AppVersionInfo>() {

			@Override
			public AppVersionInfo createFromParcel(Parcel source) {
				List<String> verExceptions = new ArrayList<String>();
				source.readStringList(new ArrayList<String>());
				AppVersionInfo result = new AppVersionInfo(verExceptions,
						source.readString(), source.readInt(),
						source.readString(), source.readString(),
						source.readString(), (source.readByte() != 0),
						source.readString());

				return result;
			}

			@Override
			public AppVersionInfo[] newArray(int size) {
				return new AppVersionInfo[0];
			}

		};

	}

	public interface OnDownAppInfoGetListener {
		public abstract void onDownAppInfoGeted(AppVersionInfo appVersionInfo);
	}

	private OnDownAppInfoGetListener onAppVersionCheckListener;

	protected String infoUrl;
	protected Context context;
	private DownloadManager manager;

	protected DownloadManager getDownloadManager() {
		if (manager == null) {
			manager = (DownloadManager) context
					.getSystemService(Activity.DOWNLOAD_SERVICE);
		}
		return manager;
	}

	public void setOnAppVersionCheckListener(
			OnDownAppInfoGetListener onAppVersionCheckListener) {
		this.onAppVersionCheckListener = onAppVersionCheckListener;
	}

	public DownAppInfoGetTask(Context context, String infoUrl) {
		super();
		this.context = context;
		this.infoUrl = infoUrl;
	}

	private AppVersionInfo reselaseAppVersion = null;

	public AppVersionInfo getReselaseAppVersion() {
		return reselaseAppVersion;
	}

	@Override
	protected void onPostExecute(AppVersionInfo result) {
		super.onPostExecute(result);
		reselaseAppVersion = result;
		if (result != null && !isCancelled()
				&& onAppVersionCheckListener != null) {
			onAppVersionCheckListener.onDownAppInfoGeted(result);
		}
	}

	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	protected void checkDownloadStatus(AppVersionInfo info) {
		Cursor cursor = getDownloadManager().query(
				new DownloadManager.Query()
						.setFilterByStatus(DownloadManager.STATUS_PAUSED
								| DownloadManager.STATUS_PENDING
								| DownloadManager.STATUS_RUNNING
								| DownloadManager.STATUS_SUCCESSFUL));
		if (cursor != null) {
			try {
				while (cursor.moveToNext()) {
					if (Uri.parse(
							cursor.getString(cursor
									.getColumnIndex(DownloadManager.COLUMN_URI)))
							.equals(Uri.parse(info.getUrl()))) {
						info.setDownloading(true);

						if (cursor.getInt(cursor
								.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {

							File localFile;
							if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
								localFile = new File(
										cursor.getString(cursor
												.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME)));
							} else
								localFile = new File(
										Uri.parse(
												cursor.getString(cursor
														.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)))
												.getEncodedPath());

							if (localFile.exists()) {
								info.setCompleteFilePath(localFile
										.getAbsolutePath());
								return;
							}
						}
						info.setCompleteFilePath(null);
						return;
					}
				}
			} finally {
				cursor.close();
			}
		}
		info.setDownloading(false);
	}

	@Override
	protected AppVersionInfo doInBackground(String... params) {

		String name = params[0];
		AppVersionInfo result = null;

		//HttpDownload httpDownload = new HttpDownload(new DownloadParams());
		try {
			String infoPage = HttpDownload.getInstance().downloadPage(infoUrl, false);

			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
			factory.setNamespaceAware(true);
			XmlPullParser xpp = factory.newPullParser();

			xpp.setInput(new StringReader(infoPage));
			int eventType = xpp.getEventType();
			String curTag = null;
			boolean inDownloadsTag = false;
			boolean inDownloadTag = false;
			while (eventType != XmlPullParser.END_DOCUMENT) {
				if (eventType == XmlPullParser.START_TAG) {
					curTag = xpp.getName();
					if (DOWNLOADS_TAG.equals(curTag)) {
						inDownloadsTag = true;
					} else if (inDownloadsTag && (DOWNLOAD_TAG.equals(curTag))) {
						inDownloadTag = true;
						if (name.equals(xpp.getAttributeValue(null, "name"))) {
							result = new AppVersionInfo(Integer.valueOf(xpp
									.getAttributeValue(null, "ver")),
									xpp.getAttributeValue(null, "uri"), name,
									xpp.getAttributeValue(null, "title"));
						}
					}

				} else if (eventType == XmlPullParser.TEXT) {
					if (result != null && curTag != null
							&& xpp.getText() != null && inDownloadTag
							&& !"".equals(xpp.getText().trim())) {
						if (curTag.equals("description")) {
							Log.d("DownAppInfoGetTask", "result:" + result);
							result.setDescription(xpp.getText());
						} else if (curTag.equals("exception")) {
							result.getVerExceptions().add(xpp.getText());
						}
					}

				} else if (eventType == XmlPullParser.END_TAG) {
					if (DOWNLOADS_TAG.equals(xpp.getName())) {
						inDownloadsTag = false;
						inDownloadTag = false;
					} else if (inDownloadTag
							&& (DOWNLOAD_TAG.equals(xpp.getName()))) {
						inDownloadTag = false;
						if (result != null) {
							return result;
						}
					}
				}
				eventType = xpp.next();
			}
			checkDownloadStatus(result);
		} catch (Exception e) {
			Log.e("DownAppInfoGetTask", e.getMessage(), e);
			return null;
		}

		return result;
	}

}
